home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / mac / hypercrd / hc2_x / tcprogud.sit / picture ƒ / screen.c < prev    next >
C/C++ Source or Header  |  1991-02-16  |  21KB  |  717 lines

  1. /*
  2. *    FILE:        screen.c
  3. *    AUTHOR:        R. Gonzalez
  4. *    CREATED:    Aug. 5, 1990
  5. *
  6. *    REVISED:    Norman Gaskill
  7. *    REV. DATE:    December 16, 1990
  8. *    CHANGES:    Add PC_Screen code
  9. *
  10. *    generic, mac-specific, and PC methods for multi-window screens.  Use
  11. *    the Mac_Screen and PC_Screen code as a guide when writing a Screen
  12. *    descendant for a new platform.
  13. */
  14.  
  15. # include    "screen.h"
  16. # include    "error.h"
  17. # include    <stdlib.h>
  18.  
  19. extern Error    *gerror;
  20.  
  21. /******************************************************************
  22. *    Initialize screen.  Derived classes call inherited method and 
  23. *    initialize device_frame.
  24. ******************************************************************/
  25. boolean    Screen::init(void)
  26. {
  27.     device_frame = new(Frame);
  28.     device_frame->init();
  29.     normalized_frame = new(Frame);
  30.     normalized_frame->init();
  31.     set_normalized_frame(0.,0.,2.,2.);
  32.     num_windows = 0;
  33.     return TRUE;
  34. }
  35.  
  36. /******************************************************************
  37. *    Add new window to screen - up to derived class.
  38. ******************************************************************/
  39. int        Screen::new_window(Frame *frame)
  40. {
  41.     return    0; /* must return something in Turbo C++? */
  42. }
  43.  
  44. /******************************************************************
  45. *    Bring window to front.  This is up to the derived class.
  46. ******************************************************************/
  47. void    Screen::make_closest(int window_num)
  48. {
  49. }
  50.  
  51. /******************************************************************
  52. *    Get coordinate frame of window in device coordinates.
  53. *    Up to derived class.
  54. ******************************************************************/
  55. void    Screen::get_window_device_frame(int window_num,
  56.                                         Frame *frame)
  57. {
  58. }
  59.  
  60. /******************************************************************
  61. *    Return screen aspect ratio: width/height in device coords.
  62. ******************************************************************/
  63. double    Screen::get_device_aspect_ratio(void)
  64. {
  65.     double    ratio;
  66.     
  67.     ratio = device_frame->width/device_frame->height;
  68.     if (ratio > 0.)
  69.         return ratio;
  70.     else
  71.         return -ratio;
  72. }
  73.  
  74. /******************************************************************
  75. *    Change coordinate system for windows and drawing routines.
  76. *    This is in terms of the width, height, and origin of
  77. *    the desired coordinate system for the whole screen.  Use
  78. *    get_device_aspect_ratio to maintain aspect ratio.
  79. ******************************************************************/
  80. void    Screen::set_normalized_frame(double x,double y,
  81.                                     double width,double height)
  82. {
  83.     normalized_frame->set(x,y,width,height);
  84. }
  85.  
  86. /******************************************************************
  87. *    Sets the current drawing window.  Up to derived class.
  88. ******************************************************************/
  89. void    Screen::set_current_window(int window_num)
  90. {
  91. }
  92.  
  93. /******************************************************************
  94. *    Sets the current drawing pen color.  Up to derived class.
  95. ******************************************************************/
  96. void    Screen::set_pen_color(color x)
  97. {
  98. }
  99.  
  100. /******************************************************************
  101. *    Sets window background to current color.  Up to derived class. 
  102. ******************************************************************/
  103. void    Screen::fill_window(void)
  104. {
  105. }
  106.  
  107. /******************************************************************
  108. *    draw_line() is used to draw lines using device coordinates.
  109. ******************************************************************/
  110. void    Screen::draw_line(Coord2* c1,Coord2* c2)
  111. {
  112.     move_to(c1);
  113.     draw_to(c2);
  114. }
  115.  
  116. /******************************************************************
  117. *    Move present pen position to new position using device
  118. *    coordinates.  Nothing is drawn.  Up to derived class.
  119. ******************************************************************/
  120. void    Screen::move_to(Coord2* c)
  121. {
  122. }
  123.  
  124. /******************************************************************
  125. *    Draw from present pen position to new position using device
  126. *    coordinates.  Up to derived class.
  127. ******************************************************************/
  128. void    Screen::draw_to(Coord2* c)
  129. {
  130. }
  131.  
  132. /******************************************************************
  133. *    mouse_button_is_down() checks whether the mouse button is down,
  134. *    returns TRUE if so, FALSE if not.  Up to derived class.  Make
  135. *    sure to override this if you use Screen::wait(), or override
  136. *    Screen::wait().  (Else you'll get an infinite "wait"!)
  137. ******************************************************************/
  138. boolean    Screen::mouse_button_is_down(void)
  139. {
  140.     return FALSE;
  141. }
  142.  
  143. /******************************************************************
  144. *    Wait until button is pressed.
  145. ******************************************************************/
  146. void    Screen::wait(void)
  147. {
  148.     while (!mouse_button_is_down())
  149.         ;
  150.     while (mouse_button_is_down())
  151.         ;
  152. }
  153.  
  154. /******************************************************************
  155. *    Destroy screen.  Derived classes call inherited method.
  156. ******************************************************************/
  157. boolean    Screen::destroy(void)
  158. {
  159.     device_frame->destroy();
  160.     delete(device_frame);
  161.     normalized_frame->destroy();
  162.     delete(normalized_frame);
  163.     
  164.     return TRUE;
  165. }
  166.  
  167. # ifdef    THINK_C
  168.  
  169. #include "DialogMgr.h"
  170. #include "EventMgr.h"
  171. #include "TextEdit.h"
  172. #include "MemoryMgr.h"
  173. #include "MenuMgr.h"
  174. #include "Quickdraw.h"
  175. #include "WindowMgr.h"
  176.  
  177. /*------------------- Mac_Screen methods -----------------------*/
  178. /*    Functions beginning with a capital letter and variables        */
  179. /*    containing capitals are declared in Mac headers, and        */
  180. /*    defined in the Macintosh Toolbox.                            */
  181.  
  182. # define    NIL_POINTER            0L
  183. # define    MOVE_TO_FRONT        -1L
  184. # define    REMOVE_ALL_EVENTS    0
  185. # define    TITLE                "\p"
  186. # define    VISIBLE                1
  187. # define    NO_GO_AWAY            0
  188. # define    NIL_REF_CON            NIL_POINTER
  189. /*    remove following line to retain menu bar.  This is recommended
  190.     to make it easier to recover from errors when debugging!    */
  191. # define    NO_MBAR
  192.  
  193. /******************************************************************
  194. *    You must call init() at the beginning of main().  Likely don't
  195. *    need all these initializations; most are taken from Mark &
  196. *    Reed's "Macintosh Programming Primer", Addison-Wesley, 1989
  197. ******************************************************************/
  198. boolean    Mac_Screen::init(void)
  199. {
  200.     double        x,
  201.                 y,
  202.                 width,
  203.                 height;
  204.     
  205.     InitGraf(&thePort);
  206.     InitFonts();
  207.     FlushEvents(everyEvent,REMOVE_ALL_EVENTS);
  208.     InitWindows();
  209.     InitMenus();
  210.     TEInit();
  211.     InitDialogs(NIL_POINTER);
  212.     InitCursor();
  213.     HideCursor();
  214.  
  215. # ifdef    NO_MBAR
  216.     old_mbar_height = MBarHeight;
  217.     MBarHeight = 0;
  218. # endif
  219.     
  220.     Screen::init();
  221.     
  222.     width = screenBits.bounds.right - screenBits.bounds.left;
  223.     height = screenBits.bounds.top - screenBits.bounds.bottom;
  224.     x = screenBits.bounds.left + width/2.;
  225.     y = screenBits.bounds.bottom + height/2.;
  226.     device_frame->set(x,y,width,height);
  227.     
  228.     normalized_frame->height =     normalized_frame->width /
  229.         get_device_aspect_ratio();
  230.         
  231.     current_window = NULL;
  232.  
  233.     return TRUE;
  234. }
  235.  
  236. /******************************************************************
  237. *    Add new window to screen
  238. ******************************************************************/
  239. int        Mac_Screen::new_window(Frame *frame)
  240. {
  241.     Rect    rectangle;
  242.     int        left,
  243.             right,
  244.             top,
  245.             bottom;
  246.     Coord2    *old_pt,
  247.             *new_pt;
  248.     Rect        mbar_rect;        /* to allow window to overlap menu */
  249.     RgnHandle    mbar_rgn;
  250.     WindowPtr    temp_window;    /*    This is required due to a
  251.                                     bug in Think C!                */
  252.     
  253.     old_pt = new(Coord2);
  254.     old_pt->init();
  255.     new_pt = new(Coord2);
  256.     new_pt->init();
  257.     
  258.     old_pt->set(frame->x-frame->width/2.,frame->y-frame->height/2.);
  259.     new_pt->convert(old_pt,normalized_frame,device_frame);
  260.     left = new_pt->x;
  261.     bottom = new_pt->y;
  262.     
  263.     old_pt->set(frame->x+frame->width/2.,frame->y+frame->height/2.);
  264.     new_pt->convert(old_pt,normalized_frame,device_frame);
  265.     right = new_pt->x;
  266.     top = new_pt->y;
  267.     
  268.     old_pt->destroy();
  269.     delete(old_pt);
  270.     new_pt->destroy();
  271.     delete(new_pt);
  272.     
  273.     SetRect(&rectangle,left,top,right,bottom);
  274.     
  275.     temp_window = NewWindow(NIL_POINTER,&rectangle,TITLE,
  276.         VISIBLE,plainDBox,MOVE_TO_FRONT,NO_GO_AWAY,NIL_REF_CON);
  277.  
  278. # ifdef    NO_MBAR
  279.     if (top < screenBits.bounds.top+old_mbar_height)
  280.     {
  281.         if (bottom < screenBits.bounds.top+old_mbar_height)
  282.             SetRect(&mbar_rect,0,0,right-left,bottom-top);
  283.         else
  284.             SetRect(&mbar_rect,0,0,right-left,
  285.                 screenBits.bounds.top+old_mbar_height-top);
  286.         mbar_rgn = NewRgn();
  287.         RectRgn(mbar_rgn,&mbar_rect);
  288.         UnionRgn(temp_window->visRgn,mbar_rgn,temp_window->visRgn);
  289.         DisposeRgn(mbar_rgn);
  290.     }
  291. # endif
  292.  
  293.     if (num_windows < MAX_WINDOWS)
  294.     {
  295.         window[num_windows++] = temp_window;
  296.         set_current_window(num_windows-1);
  297.         return num_windows-1;
  298.     }
  299.     else
  300.     {
  301.         gerror->report("Ran out of windows");
  302.         DisposeWindow(temp_window);
  303.         return num_windows-1;
  304.     }
  305. }
  306.  
  307. /******************************************************************
  308. *    Bring window to front.
  309. ******************************************************************/
  310. void    Mac_Screen::make_closest(int window_num)
  311. {
  312.     if (window_num > -1 && window_num < num_windows)
  313.         SelectWindow(window[window_num]);
  314.     else
  315.         gerror->report("Illegal window number");
  316. }
  317.  
  318. /******************************************************************
  319. *    Get coordinate frame of window in device coordinates.
  320. ******************************************************************/
  321. void    Mac_Screen::get_window_device_frame(int window_num,
  322.                                             Frame *frame)
  323. {
  324.     double    x,
  325.             y,
  326.             width,
  327.             height;
  328.             
  329.     if (window_num > -1 && window_num < num_windows)
  330.     {
  331.         width =        window[window_num]->portRect.right -
  332.                     window[window_num]->portRect.left;
  333.         height =    window[window_num]->portRect.top -
  334.                     window[window_num]->portRect.bottom;
  335.         x =         window[window_num]->portRect.left + width/2.;
  336.         y =         window[window_num]->portRect.bottom + height/2.;
  337.         frame->set(x,y,width,height);
  338.     }
  339.     else
  340.         gerror->report("Illegal window number");
  341. }
  342.  
  343. /******************************************************************
  344. *    Sets the current drawing window.
  345. ******************************************************************/
  346. void    Mac_Screen::set_current_window(int window_num)
  347. {
  348.     if (window_num > -1 && window_num < num_windows)
  349.     {
  350.         current_window = window[window_num];
  351.         SetPort(current_window);
  352.     }
  353.     else
  354.         gerror->report("Illegal window number");
  355. }
  356.  
  357. /******************************************************************
  358. *    sets the current drawing color.  The colors are defined
  359. *    in "Quickdraw.h".  Call set_current_window() first!
  360. ******************************************************************/
  361. void    Mac_Screen::set_pen_color(color x)
  362. {
  363.     if (current_window != NULL)
  364.         switch ((int) x)
  365.         {
  366.             case 0:        ForeColor(blackColor);
  367.                         break;
  368.             case 1:        ForeColor(whiteColor);
  369.                         break;
  370.             case 2:        ForeColor(redColor);
  371.                         break;
  372.             case 3:        ForeColor(yellowColor);
  373.                         break;
  374.             case 4:        ForeColor(greenColor);
  375.                         break;
  376.             case 5:        ForeColor(blueColor);
  377.                         break;
  378.             case 6:        ForeColor(cyanColor);
  379.                         break;
  380.             case 7:        ForeColor(magentaColor);
  381.                         break;
  382.             default:    break;
  383.         }
  384.     else
  385.         gerror->report("Can't set color with no windows");
  386. }
  387.  
  388. /******************************************************************
  389. *    calls the appropriate Mac Toolbox function to make the window
  390. *    the current color.   Call set_current_window() first!
  391. ******************************************************************/
  392. void    Mac_Screen::fill_window(void)
  393. {
  394.     if (current_window != NULL)
  395.         FillRect(&(current_window->portRect),black);
  396.     else
  397.         gerror->report("Can't fill window with no windows");
  398. }
  399.  
  400. /******************************************************************
  401. *    Move present pen position to new position using device
  402. *    coordinates.  Call set_current_window() first!
  403. ******************************************************************/
  404. void    Mac_Screen::move_to(Coord2* c)
  405. {
  406.     if (current_window != NULL)
  407.         MoveTo((int) c->x,(int) c->y);
  408.     else
  409.         gerror->report("Can't move_to() with no windows");
  410. }
  411.  
  412. /******************************************************************
  413. *    Draw from present pen position to new position using device
  414. *    coordinates.  Call set_current_window() first!
  415. ******************************************************************/
  416. void    Mac_Screen::draw_to(Coord2* c)
  417. {
  418.     if (current_window != NULL)
  419.         LineTo((int) c->x,(int) c->y);
  420.     else
  421.         gerror->report("Can't draw_to() with no windows");
  422. }
  423.  
  424. /******************************************************************
  425. *    mouse_button_is_down() checks whether the mouse button is down,
  426. *    returns TRUE if so, FALSE if not.
  427. ******************************************************************/
  428. boolean    Mac_Screen::mouse_button_is_down(void)
  429. {
  430.     return Button();
  431. }
  432.  
  433. /******************************************************************
  434. *    Destroy screen.
  435. ******************************************************************/
  436. boolean    Mac_Screen::destroy(void)
  437. {
  438.     int        window_num;
  439.     
  440.     Screen::destroy();
  441.     
  442.     for (window_num=0 ; window_num<num_windows ; window_num++)
  443.         DisposeWindow(window[window_num]);
  444.  
  445. # ifdef    NO_MBAR
  446.     MBarHeight = old_mbar_height;
  447. # endif
  448.     
  449.     return TRUE;
  450. }
  451.  
  452. # else
  453.  
  454. /*-------------------------------- PC_Screen methods ---------------------------------*/
  455.  
  456. /*-----------------NOTE: file EGAVGA.BGI must be in current directory-----------------*/
  457.  
  458. # include <stdio.h>
  459. # define __COLORS         //for THINK_C
  460. # include <conio.h>
  461. # include <graphics.h>    //BORLAND Turbo C++ library of graphics functions
  462. # undef __COLORS          //for THINK_C
  463. # define  LIGHTGRAY  7    //for use by floodfill
  464.  
  465. int current_window = -1;         //keeps track of current window number
  466. boolean window_defined = FALSE;  //valid window variable
  467. int win_data [MAX_WINDOWS] [6];  //window data array
  468.  
  469. /******************************************************************
  470. * You must call init() at the beginning of main().  
  471. ******************************************************************/
  472. boolean PC_Screen::init(void)
  473. {
  474.   int x,y,width,height;
  475.   int graphdriver = DETECT, graphmode, error_code;
  476.  
  477.   Screen::init();
  478.   initgraph(&graphdriver, &graphmode, "..\\bgi"); //Initialize graphics,
  479.   error_code = graphresult();                     //system must be EGA or VGA
  480.   if (error_code != grOk)                         //If no graphics
  481.     return(FALSE);                                //hardware found is found
  482.   if ((graphdriver != EGA) && (graphdriver != VGA))
  483.   {
  484.     closegraph();
  485.     return FALSE;
  486.   }
  487.   width = getmaxx();
  488.   height = getmaxy();
  489.   x = width/2;
  490.   y = height/2;
  491.   device_frame->set(x,y,width,-height);
  492.   normalized_frame->height = normalized_frame->width / 
  493.                              get_device_aspect_ratio();
  494.   return(TRUE);                                   //Graphics OK return "true"
  495. }
  496.  
  497. /******************************************************************
  498. * Add new window to screen
  499. ******************************************************************/
  500. int PC_Screen::new_window(Frame *frame)
  501. {
  502.   int left,
  503.       right,
  504.       top,
  505.       bottom;
  506.   Coord2  *old_pt,
  507.           *new_pt;
  508.   
  509.   old_pt = new(Coord2);
  510.   old_pt->init();
  511.   new_pt = new(Coord2);
  512.   new_pt->init();
  513.   
  514.   old_pt->set(frame->x-frame->width/2.,frame->y-frame->height/2.);
  515.   new_pt->convert(old_pt,normalized_frame,device_frame);
  516.   left = new_pt->x;
  517.   bottom = new_pt->y;
  518.   
  519.   old_pt->set(frame->x+frame->width/2.,frame->y+frame->height/2.);
  520.   new_pt->convert(old_pt,normalized_frame,device_frame);
  521.   right = new_pt->x;
  522.   top = new_pt->y;
  523.   
  524.   old_pt->destroy();
  525.   delete(old_pt);
  526.   new_pt->destroy();
  527.   delete(new_pt);
  528.  
  529.   if (num_windows < MAX_WINDOWS)
  530.   {
  531.     setviewport(left,top,right,bottom,1); //1=truncate output
  532.     win_data[num_windows][0] = left;
  533.     win_data[num_windows][1] = top;
  534.     win_data[num_windows][2] = right;
  535.     win_data[num_windows][3] = bottom;
  536.     current_window = num_windows;
  537.     num_windows++;
  538.     return num_windows-1;
  539.   }
  540.   else
  541.   {
  542.     gerror->report("Ran out of windows");
  543.     return num_windows;
  544.   }
  545. }
  546.  
  547. /******************************************************************
  548. * Bring window to front.
  549. ******************************************************************/
  550. void  PC_Screen::make_closest(int window_num)
  551. {
  552.   if (window_num > -1 && window_num < num_windows)
  553.   {
  554.     current_window = window_num;
  555.     setviewport(win_data[current_window][0],      //resets viewport
  556.                 win_data[current_window][1],
  557.                 win_data[current_window][2],
  558.                 win_data[current_window][3],1);   //1=truncate output
  559.     setfillstyle(SOLID_FILL, win_data[current_window][4]);  //set and
  560.     floodfill(2,2,LIGHTGRAY);                     //flood fill current window
  561.     setcolor(win_data[current_window][5]);        //reset draw color
  562.   }
  563.   else
  564.     gerror->report("Illegal window number");
  565. }
  566.  
  567. /******************************************************************
  568. * Get coordinate frame of window in device coordinates.
  569. ******************************************************************/
  570. void  PC_Screen::get_window_device_frame(int window_num,Frame *frame)
  571. {
  572.   int x,
  573.       y,  
  574.       width,
  575.       height;
  576.   struct viewporttype viewinfo;
  577.  
  578.   if (window_num > -1 && window_num < num_windows)
  579.   {
  580.     getviewsettings(&viewinfo);
  581.     width = viewinfo.right - viewinfo.left;
  582.     height = viewinfo.bottom - viewinfo.top;
  583.     x = width/2;
  584.     y = height/2;
  585.  
  586.     frame->set(x,y,width,-height);
  587.   }
  588.   else
  589.     gerror->report("Illegal window number");
  590. }
  591.  
  592. /******************************************************************
  593. * Sets the current drawing window.
  594. ******************************************************************/
  595. void  PC_Screen::set_current_window(int window_num)
  596. {
  597.   if (window_num > -1 && window_num < num_windows)
  598.   {
  599.     window_defined = TRUE;
  600.     current_window = window_num;
  601.     setviewport(win_data[current_window][0],      //resets viewport
  602.                 win_data[current_window][1],
  603.                 win_data[current_window][2],
  604.                 win_data[current_window][3],1);   //1=truncate output
  605.   }
  606.   else
  607.     gerror->report("Illegal window number");
  608. }
  609.  
  610. /******************************************************************
  611. * sets the current drawing color.  Call set_current_window() first!
  612. *----------------------------------------------------------------
  613. * Note from R. Gonzalez:  N. Gaskill had difficulty here because
  614. * the Turbo C++ file "graphics.h" conflicted with
  615. * my use of the identifier "color" and/or with my list of color
  616. * constants, as defined in my "color.h".  To get around this
  617. * he had to use "# define __COLORS" and was unable to take advan-
  618. * tage of the names given in "graphics.h".  I think he could have
  619. * gotten around this by momentarily #undef-ing my constants and
  620. * #define-ing constants with new names for the ones given in
  621. * graphics.h.  As it is, however, he is forced to use numerical
  622. * constants below.
  623. ******************************************************************/
  624. void  PC_Screen::set_pen_color(int color)
  625. {
  626.   if (window_defined)
  627.   {
  628.     switch (color)                                //correct colors for PC
  629.     {
  630.       case 0:  color = 0;
  631.         break;
  632.       case 1:  color = 15;
  633.         break;
  634.       case 2:  color = 4;
  635.         break;
  636.       case 3:  color = 14;
  637.         break;
  638.       case 4:  color = 2;
  639.         break;
  640.       case 5:  color = 1;
  641.         break;
  642.       case 6:  color = 3;
  643.         break;
  644.       case 7:  color = 5;
  645.         break;
  646.       default: break;
  647.     }
  648.     setcolor(color);                              //set draw color
  649.     setfillstyle(SOLID_FILL, color);              //set flood fill color
  650.     win_data[current_window][5] = color;          //save draw color 
  651.   }
  652.   else
  653.     gerror->report("Can't set color with no windows");
  654. }
  655.  
  656. /******************************************************************
  657. * Make the window the current color.   Call set_current_window() first!
  658. ******************************************************************/
  659. void  PC_Screen::fill_window(void)
  660. {
  661.   if (window_defined)
  662.     {
  663.         clearviewport();                              //clear for next
  664.         floodfill(2,2,LIGHTGRAY);                     //fill window
  665.     win_data[current_window][4] = getcolor();     //save fill color
  666.   }
  667.   else
  668.     gerror->report("Can't fill window with no windows");
  669. }
  670.  
  671. /******************************************************************
  672. * Move present pen position to new position using device
  673. * coordinates.  Call set_current_window() first!
  674. ******************************************************************/
  675. void  PC_Screen::move_to(Coord2* c)
  676. {
  677.   if (window_defined)
  678.     moveto((int) c->x,(int) c->y);
  679.   else
  680.     gerror->report("Can't move_to() with no windows");
  681. }
  682.  
  683. /******************************************************************
  684. * Draw from present pen position to new position using device
  685. * coordinates.  Call set_current_window() first!
  686. ******************************************************************/
  687. void  PC_Screen::draw_to(Coord2* c)
  688. {
  689.   if (window_defined)
  690.     lineto((int) c->x,(int) c->y);
  691.   else
  692.     gerror->report("Can't draw_to() with no windows");
  693. }
  694.  
  695. /******************************************************************
  696. * look for keyhit.
  697. ******************************************************************/
  698. void  PC_Screen::wait(void)
  699. {
  700.   printf("Press any key to exit");
  701.   getch();
  702. }
  703.  
  704. /******************************************************************
  705. * Destroy screen.
  706. ******************************************************************/
  707. boolean PC_Screen::destroy(void)
  708. {
  709.   int window_num;
  710.   
  711.   Screen::destroy();
  712.   closegraph(); 
  713.   return TRUE;
  714. }
  715.  
  716. # endif
  717.